import bcrypt
import jwt
from datetime import datetime, timedelta
from typing import Dict, Union

from utils.businessException import BusinessException


class PasswordManager:
    def hash_password(self, plain_password: str) -> str:
        # 生成盐
        salt = bcrypt.gensalt()
        # 对密码进行哈希处理
        hashed_password = bcrypt.hashpw(plain_password.encode('utf-8'), salt)
        return hashed_password.decode('utf-8')

    def verify_password(self, plain_password: str, hashed_password: str) -> bool:
        # 验证密码是否匹配
        return bcrypt.checkpw(plain_password.encode('utf-8'), hashed_password.encode('utf-8'))


class TokenManager:
    def __init__(self, secret_key: str = "9103feed-94a2-4272-994c-360479fb0532", algorithm: str = "HS256", expiration_minutes: int = 60):
        self.secret_key = secret_key
        self.algorithm = algorithm
        self.expiration_minutes = expiration_minutes

    def create_token(self, data: Dict[str, Union[str, int]], _expiration_minutes: int = None) -> tuple:
        if (_expiration_minutes is None):
            _expiration_minutes = self.expiration_minutes
        payload = data.copy()
        expiration = datetime.now() + timedelta(minutes=_expiration_minutes)
        payload.update({"exp": expiration})
        token = jwt.encode(payload, self.secret_key, algorithm=self.algorithm)
        return (token, expiration)

    def verify_token(self, token: str) -> Dict[str, Union[str, int]]:
        try:
            decoded_data = jwt.decode(
                token, self.secret_key, algorithms=[self.algorithm])
            return decoded_data
        except jwt.ExpiredSignatureError:
            raise BusinessException(status_code=401,code=401,msg="Token has expired")
        except jwt.InvalidTokenError:
            raise BusinessException(status_code=401,code=401,msg="Invalid token")
